package com.ikas.ai.server.module.flow.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ikas.ai.server.common.parser.AiMaintainParser;
import com.ikas.ai.server.common.parser.model.AiMaintainMetaData;
import com.ikas.ai.server.common.parser.model.FlowNodeLineMetaLine;
import com.ikas.ai.server.common.parser.model.FlowNodeMetaData;
import com.ikas.ai.server.error.BusinessException;
import com.ikas.ai.server.module.flow.dao.FlowDAO;
import com.ikas.ai.server.module.flow.dto.FlowDTO;
import com.ikas.ai.server.module.flow.enums.NodeConfigSymbol;
import com.ikas.ai.server.module.flow.model.Flow;
import com.ikas.ai.server.module.flow.model.FlowNode;
import com.ikas.ai.server.module.flow.model.FlowNodeLine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @Description: 流程Service
 *
 * @Author: qi.yilai
 * @Date: 2023/1/17 16:14
 * @Version: 1.0.0
 **/
@Service
public class FlowService extends ServiceImpl<FlowDAO, Flow> {

    @Autowired
    private FlowNodeService flowNodeService;

    @Autowired
    private FlowNodeLineService flowNodeLineService;

    /**
     * 保存或更新流程
     *
     * @param flowDTO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Flow saveOrUpdate(FlowDTO flowDTO) {
        Flow flow = new Flow();
        flow.setId(flowDTO.getId());
        flow.setName(flowDTO.getName());
        flow.setContent(flowDTO.getContent());
        flow.setSceneId(flowDTO.getSceneId());
        flow.setCreator(flowDTO.getCreator());
        if (Objects.isNull(flowDTO.getId())) {
            flow.setCreateTime(new Date());
            save(flow);
        } else {
            Flow oldFlow = getById(flow.getId());
            if (Objects.equals(oldFlow.getContent(), flow.getContent())) {
                return oldFlow;
            }
            flow.setUpdateTime(new Date());
            updateById(flow);
        }

        flowNodeService.deleteFlowNodesByFlowId(flow.getId());
        flowNodeLineService.deleteFlowLine(flow.getId());
        String content = replaceCompareCharacter(flowDTO.getContent());
        AiMaintainMetaData aiMaintainMetaData = AiMaintainParser.parse(content);
        if (aiMaintainMetaData.getNodeMap() == null) {
            throw new BusinessException("画布内容为空，不能保存！");
        }
        saveNodeAndLine(flow, aiMaintainMetaData);
        return flow;
    }

    /**
     * 保存节点和连线
     *
     * @param flow
     * @param aiMaintainMetaData
     */
    private void saveNodeAndLine(Flow flow, AiMaintainMetaData aiMaintainMetaData) {
        Map<String, FlowNodeMetaData> flowNodeMetaDataMap = aiMaintainMetaData.getNodeMap();
        Map<String, FlowNode> nodeMap = Maps.newHashMap();

        for (Map.Entry<String, FlowNodeMetaData> entry : flowNodeMetaDataMap.entrySet()) {
            FlowNodeMetaData flowNodeMetaData = entry.getValue();
            FlowNode flowNode = createFlowNode(flow, flowNodeMetaData);
            flowNodeService.save(flowNode);
            nodeMap.put(entry.getKey(), flowNode);
        }

        List<FlowNodeLineMetaLine> lines = aiMaintainMetaData.getLines();
        List<FlowNodeLine> lineList = Lists.newArrayList();
        lines.forEach(line -> {
            FlowNodeLine flowNodeLine = new FlowNodeLine();
            flowNodeLine.setFlowId(flow.getId());
            flowNodeLine.setSceneId(flow.getSceneId());
            flowNodeLine.setFromNode(nodeMap.get(line.getFormNodeId()).getId());
            flowNodeLine.setToNode(nodeMap.get(line.getToNodeId()).getId());
            lineList.add(flowNodeLine);
        });
        flowNodeLineService.saveBatch(lineList);
    }

    private FlowNode createFlowNode(Flow flow, FlowNodeMetaData flowNodeMetaData) {
        FlowNode flowNode = new FlowNode();
        flowNode.setFlowId(flow.getId());
        flowNode.setSceneId(flow.getSceneId());
        flowNode.setName(flowNodeMetaData.getName());
        flowNode.setX6InstanceId(flowNodeMetaData.getId());
        flowNode.setNodeType(flowNodeMetaData.getNodeType().byteValue());
        flowNode.setNodeTypeName(flowNodeMetaData.getNodeTypeName());
        flowNode.setParamValue(flowNodeMetaData.getValue());
        return flowNode;
    }

    /**
     * 根据场景获取id获取流程
     *
     * @param sceneId
     * @return
     */
    public Flow getFlowBySceneId(Long sceneId) {
        LambdaQueryWrapper<Flow> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Flow::getSceneId, sceneId);
        return getOne(lambdaQueryWrapper);
    }

    private String replaceCompareCharacter(String content) {
        if (content.contains(NodeConfigSymbol.LT.getValue())) {
            content = content.replaceAll(NodeConfigSymbol.LT.getValue(), NodeConfigSymbol.LT.getSymbol());
        }
        if (content.contains(NodeConfigSymbol.LE.getValue())) {
            content = content.replaceAll(NodeConfigSymbol.LE.getValue(), NodeConfigSymbol.LE.getSymbol());
        }
        if (content.contains(NodeConfigSymbol.GT.getValue())) {
            content = content.replaceAll(NodeConfigSymbol.GT.getValue(), NodeConfigSymbol.GT.getSymbol());
        }
        if (content.contains(NodeConfigSymbol.GE.getValue())) {
            content = content.replaceAll(NodeConfigSymbol.GE.getValue(), NodeConfigSymbol.GE.getSymbol());
        }
        if (content.contains(NodeConfigSymbol.AND.getValue())) {
        	content = content.replaceAll(NodeConfigSymbol.AND.getValue(), NodeConfigSymbol.AND.getSymbol());
        }
        return content;
    }
}
